home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Technology Seed / ADC Seed CD - July 1999.toast / USB / Mac OS USB DDK v1.2 / Examples / USBKeypad / USBKeypad.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-15  |  13.6 KB  |  391 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        USBKeypad.c
  3.  
  4.     Contains:    HID Module for USB Keyboard
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "USBKeypad.h"
  19.  
  20. usbMacAllyPBStruct myParamBlock;
  21. usbMacAllyPBStruct shimParamBlock;
  22.  
  23.  
  24. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock);
  25.  
  26. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  27. {
  28.     paramblock->usbReference = theDeviceRef;
  29.     paramblock->pbVersion = kUSBCurrentPBVersion;
  30.     paramblock->usb.cntl.WIndex = 0;             
  31.     paramblock->usbBuffer = nil;        
  32.     paramblock->usbStatus = noErr;
  33.     paramblock->usbReqCount = 0;
  34.     paramblock->usb.cntl.WValue = 0;
  35.     paramblock->usbFlags = 0;
  36.     paramblock->usbOther = 0;
  37. }
  38.  
  39. static Boolean immediateError(OSStatus err)
  40. {
  41.     return((err != kUSBPending) && (err != noErr) );
  42. }
  43.  
  44. void InitiateTransaction(USBPB *pb)
  45. {
  46. register usbMacAllyPBStruct *pMacAllyPB;
  47. OSStatus myErr;
  48.  
  49.     pMacAllyPB = (usbMacAllyPBStruct *)(pb);
  50.     pMacAllyPB->transDepth++;
  51.     if (pMacAllyPB->transDepth < 0)
  52.     {
  53.         USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pUSBHIDMacAllyTenKey: transDepth < 0 (initiation)", pMacAllyPB->pb.usbRefcon );
  54.     }
  55.     
  56.     if (pMacAllyPB->transDepth > 1)
  57.     {
  58.         USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pUSBHIDMacAllyTenKey: transDepth > 1 (initiation)", pMacAllyPB->pb.usbRefcon );
  59.     }
  60.     
  61.     switch(pMacAllyPB->pb.usbRefcon & ~kRetryTransaction)
  62.     {
  63.         case kSetKeyboardLEDs:
  64.             InitParamBlock(pMacAllyPB->deviceRef, &pMacAllyPB->pb);
  65.             
  66.             pMacAllyPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  67.             
  68.             pMacAllyPB->pb.usb.cntl.BRequest = kHIDRqSetReport;
  69.             pMacAllyPB->pb.usb.cntl.WValue = (kHIDRtOutputReport << 8); 
  70.             pMacAllyPB->pb.usb.cntl.WIndex = pMacAllyPB->pInterfaceDescriptor->interfaceNumber;
  71.             
  72.             pMacAllyPB->pb.usbBuffer = (Ptr)&pMacAllyPB->hidReport[0];
  73.             pMacAllyPB->pb.usbReqCount = 1;
  74.                 
  75.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  76.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  77.             
  78.             myErr = USBDeviceRequest(&pMacAllyPB->pb);
  79.             if(immediateError(myErr))
  80.             {
  81.                 USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pUSBHIDMacAllyTenKey: kSetKeyboardLEDs - immediate error", myErr);
  82.             }
  83.             break;
  84.  
  85.         case kFindInterface:
  86.             InitParamBlock(pMacAllyPB->deviceRef, &pMacAllyPB->pb);
  87.             pMacAllyPB->pb.usb.cntl.WIndex = 0;
  88.             pMacAllyPB->pb.usb.cntl.WValue = 0;
  89.             pMacAllyPB->pb.usbClassType = kUSBHIDInterfaceClass;
  90.             pMacAllyPB->pb.usbSubclass = kUSBNoInterfaceSubClass;
  91.             pMacAllyPB->pb.usbProtocol = kUSBKeyboardInterfaceProtocol;
  92.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  93.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  94.             myErr = USBFindNextInterface(pb);
  95.             if(immediateError(myErr))
  96.             {
  97.                 USBExpertFatalError(pMacAllyPB->pb.usbReference, kUSBInternalErr, "\pMacAlly TenKey Driver: USBFindNextInterface (immediate error)", myErr);
  98.                 pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  99.             }
  100.             break;
  101.             
  102.         case kOpenDevice:
  103.             InitParamBlock(pMacAllyPB->deviceRef, &pMacAllyPB->pb);
  104.             pMacAllyPB->pb.usb.cntl.WValue = pMacAllyPB->configurationNumber;
  105.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  106.             
  107.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  108.             myErr = USBOpenDevice(pb);
  109.             if(immediateError(myErr))
  110.             {
  111.                 USBExpertFatalError(pMacAllyPB->pb.usbReference, kUSBInternalErr, "\pMacAlly TenKey Driver: USBOpenDevice (immediate error)", myErr);
  112.                 pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  113.             }
  114.             break;
  115.             
  116.         case kNewInterfaceRef:
  117.             InitParamBlock(pMacAllyPB->deviceRef, &pMacAllyPB->pb);
  118.             pMacAllyPB->pb.usb.cntl.WIndex = pMacAllyPB->interfaceNumber;
  119.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  120.             
  121.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  122.             myErr = USBNewInterfaceRef(pb);
  123.             if(immediateError(myErr))
  124.             {
  125.                 USBExpertFatalError(pMacAllyPB->pb.usbReference, kUSBInternalErr, "\pMacAlly TenKey Driver: USBNewInterfaceRef (immediate error)", myErr);
  126.                 pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  127.             }
  128.             break;
  129.             
  130.         case kConfigureInterface:
  131.             InitParamBlock(pMacAllyPB->interfaceRef, &pMacAllyPB->pb);
  132.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  133.             
  134.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  135.             myErr = USBConfigureInterface(pb);
  136.             if(immediateError(myErr))
  137.             {
  138.                 USBExpertFatalError(pMacAllyPB->pb.usbReference, kUSBInternalErr, "\pMacAlly TenKey Driver: USBConfigureInterface (immediate error)", myErr);
  139.                 pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  140.             }
  141.             break;
  142.             
  143.         case kGetReportDescriptor:
  144.             InitParamBlock(pMacAllyPB->deviceRef, &pMacAllyPB->pb);
  145.             pMacAllyPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBInterface);
  146.             pMacAllyPB->pb.usb.cntl.BRequest = kUSBRqGetDescriptor;
  147.             pMacAllyPB->pb.usb.cntl.WValue = (0x22 << 8) + 1;             // get the first report descriptor
  148.             pMacAllyPB->pb.usb.cntl.WIndex = pMacAllyPB->interfaceNumber;
  149.             pMacAllyPB->pb.usbReqCount = 0x66;
  150.             pMacAllyPB->pb.usbBuffer = pMacAllyPB->hidReportDescriptor;
  151.             
  152.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  153.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  154.             myErr = USBDeviceRequest(pb);
  155.             if(immediateError(myErr))
  156.             {
  157.                 USBExpertFatalError(pMacAllyPB->pb.usbReference, kUSBInternalErr, "\pMacAlly TenKey Driver: kGetReportDescriptor - immediate error", myErr);
  158.             }
  159.             break;
  160.         
  161.         case kFindInterruptPipe:
  162.             USBExpertStatus(pMacAllyPB->interfaceRef, "\pUSBHIDMacAllyTenKey: kFindInterruptPipe - interfaceRef", pMacAllyPB->interfaceRef);
  163.             InitParamBlock(pMacAllyPB->interfaceRef, &pMacAllyPB->pb);
  164.             pMacAllyPB->pb.usbFlags = kUSBIn;
  165.             pMacAllyPB->pb.usbClassType = kUSBInterrupt; 
  166.             
  167.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  168.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  169.             myErr = USBFindNextPipe(&pMacAllyPB->pb);
  170.             if (immediateError(myErr))
  171.             {
  172.                 USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pMacAlly TenKey Driver: kFindInterruptPipe (immediate error)", myErr);
  173.                 pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  174.             }
  175.             break;
  176.             
  177.         case kReadInterruptPipe:
  178.             InitParamBlock(pMacAllyPB->pipeRef, &pMacAllyPB->pb);
  179.  
  180.             pMacAllyPB->pb.usbBuffer = (Ptr)pMacAllyPB->hidReport;
  181.             pMacAllyPB->pb.usbReqCount = 4;
  182.             pMacAllyPB->pb.usb.cntl.WIndex = pMacAllyPB->interfaceNumber;    
  183.             
  184.             pMacAllyPB->pb.usbRefcon |= kCompletionPending;
  185.             pMacAllyPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  186.             myErr = USBIntRead(&pMacAllyPB->pb);
  187.             if(immediateError(myErr))
  188.             {
  189.                 USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pMacAlly TenKey Driver: kReadInterruptPipe (ImmediateError)", myErr);
  190.             }
  191.             break;
  192.             
  193.             
  194.         default:
  195.             USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pUSBHIDMacAllyTenKey - Transaction completed with bad refcon value", pMacAllyPB->pb.usbRefcon );
  196.             pMacAllyPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  197.             break;
  198.     }
  199.     
  200. // At this point the control is returned to the system.  If a USB transaction
  201. // has been initiated, then it will call the Complete procs
  202. // (below) to handle the results of the transaction.
  203. }
  204.  
  205. void TransactionCompletionProc(USBPB *pb)
  206. {
  207. unsigned char    * errstring;
  208. register usbMacAllyPBStruct *pMacAllyPB;
  209. USBPipeState pipeState;
  210.  
  211.     pMacAllyPB = (usbMacAllyPBStruct *)(pb);
  212.     pMacAllyPB->transDepth--;
  213.     if (pMacAllyPB->transDepth < 0)
  214.     {
  215.         USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pUSBHIDMacAllyTenKey: transDepth < 0 (completion)", pMacAllyPB->pb.usbRefcon );
  216.     }
  217.     
  218.     if (pMacAllyPB->transDepth > 1)
  219.     {
  220.         USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pUSBHIDMacAllyTenKey: transDepth > 1 (completion)", pMacAllyPB->pb.usbRefcon );
  221.     }
  222.     
  223.     if(pMacAllyPB->pb.usbStatus != noErr)                                                    // was there an error?
  224.     {
  225.         switch(pMacAllyPB->pb.usbRefcon & 0x0fff)                                            // yes, so show where the error occurred
  226.         {
  227.             case kFindInterface:                  errstring = "\pWacom Driver: Error during kFindInterface"; break;
  228.             case kOpenDevice:                    errstring = "\pWacom Driver: Error during kOpenDevice"; break;
  229.             case kNewInterfaceRef:                errstring = "\pWacom Driver: Error during kNewInterfaceRef"; break;
  230.             case kConfigureInterface:              errstring = "\pWacom Driver: Error during kConfigureInterface"; break;
  231.             case kGetReportDescriptor:              errstring = "\pWacom Driver: Error during kGetReportDescriptor"; break;
  232.             case kFindInterruptPipe:              errstring = "\pWacom Driver: Error during kFindInterruptPipe"; break;
  233.             case kReadInterruptPipe:              errstring = "\pWacom Driver: Error during kReadInterruptPipe"; break;
  234.         };
  235.         USBExpertFatalError(pMacAllyPB->deviceRef, pMacAllyPB->pb.usbStatus, errstring, (pMacAllyPB->pb.usbRefcon & 0x0fff));
  236.         
  237.         pMacAllyPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);                // set up to retry the transaction
  238.         pMacAllyPB->pb.usbRefcon |= kRetryTransaction;
  239.         pMacAllyPB->retryCount--;
  240.         
  241.         if ((!pMacAllyPB->retryCount)    || (pMacAllyPB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  242.         {                                                                                    // or received an abort?
  243.             USBExpertStatus(pMacAllyPB->deviceRef, "\pUSBHIDMacAllyTenKey: Pipe abort or unable to recover from error", pMacAllyPB->deviceRef);
  244.             pMacAllyPB->pb.usbRefcon = kReturnFromDriver;                                    // if so, just exit.
  245.         }
  246.         else                                                                                // if it didn't abort and there's retries left, then...
  247.         {
  248.             if (pMacAllyPB->pipeRef)                                                        // check if the pipe is open.
  249.             {
  250.                 USBGetPipeStatusByReference(pMacAllyPB->pipeRef, &pipeState);                // yes, so what it's state?
  251.                 if (pipeState != kUSBActive)                                                // if it's not active, try to clear it.  It might be stalled...
  252.                 {
  253.                     USBExpertStatus(pMacAllyPB->deviceRef, "\pUSBHIDMacAllyTenKey: Pipe is open and stalled, clearing stall...", pMacAllyPB->deviceRef);
  254.                     USBClearPipeStallByReference(pMacAllyPB->pipeRef);
  255.                 }
  256.             }
  257.         }
  258.     }
  259.     else
  260.     {
  261.         pMacAllyPB->pb.usbRefcon &= ~kRetryTransaction;
  262.         pMacAllyPB->retryCount = kKeyboardRetryCount;
  263.     }
  264.  
  265.     if (pMacAllyPB->pb.usbRefcon & kCompletionPending)             
  266.     {                                                
  267.         pMacAllyPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  268.         switch(pMacAllyPB->pb.usbRefcon)
  269.         {
  270.             case kSetKeyboardLEDs:
  271.                 pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  272.                 break;
  273.                 
  274.             case kFindInterface:
  275.                 if ((pMacAllyPB->pb.usbClassType == kUSBHIDInterfaceClass) && 
  276.                     (pMacAllyPB->pb.usbSubclass == kUSBNoInterfaceSubClass) &&
  277.                     (pMacAllyPB->pb.usbProtocol == kUSBKeyboardInterfaceProtocol))
  278.                 {
  279.                     pMacAllyPB->pb.usbRefcon = kOpenDevice;
  280.                     pMacAllyPB->interfaceNumber = pMacAllyPB->pb.usb.cntl.WIndex;
  281.                     pMacAllyPB->configurationNumber = pMacAllyPB->pb.usb.cntl.WValue;
  282.                 }
  283.                 else
  284.                 {
  285.                     pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  286.                 }
  287.                 break;
  288.                 
  289.             case kOpenDevice:
  290.                 pMacAllyPB->pb.usbRefcon = kNewInterfaceRef;
  291.                 break;
  292.                 
  293.             case kNewInterfaceRef:
  294.                 pMacAllyPB->interfaceRef = pMacAllyPB->pb.usbReference;
  295.                 pMacAllyPB->pb.usbRefcon = kConfigureInterface;
  296.                 break;
  297.             
  298.             case kConfigureInterface:
  299.                 pMacAllyPB->pb.usbRefcon = kFindInterruptPipe;
  300.                 break;
  301.             
  302.             case kGetReportDescriptor:
  303.                 pMacAllyPB->pb.usbRefcon = kFindInterruptPipe;
  304.                 break;
  305.                 
  306.             case kFindInterruptPipe:
  307.                 if ((pMacAllyPB->pb.usbClassType == kUSBInterrupt) && 
  308.                     (pMacAllyPB->pb.usbFlags == kUSBIn))
  309.                 {
  310.                     pMacAllyPB->hidReportSize = pMacAllyPB->pb.usb.cntl.WValue;
  311.                     pMacAllyPB->pipeRef = pMacAllyPB->pb.usbReference;
  312.                     pMacAllyPB->pb.usbRefcon = kReadInterruptPipe;
  313.                 }
  314.                 else
  315.                 {
  316.                     pMacAllyPB->pb.usbRefcon = kReturnFromDriver;
  317.                 }
  318.                 break;
  319.                 
  320.             case kReadInterruptPipe:
  321.                 //DebugStr("\pMacAlly read completed");
  322.                 ProcessInterruptReport(pMacAllyPB->hidReport);
  323.                 pMacAllyPB->pb.usbRefcon = kReadInterruptPipe;
  324.                 break;
  325.                 
  326.             default:
  327.                 USBExpertFatalError(pMacAllyPB->deviceRef, kUSBInternalErr, "\pUSBHIDMacAllyTenKey - Transaction completed with bad refcon value", pMacAllyPB->pb.usbRefcon );
  328.                 pMacAllyPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  329.                 break;
  330.         }
  331.     }
  332.     if (!(pMacAllyPB->pb.usbRefcon & kReturnFromDriver))
  333.         InitiateTransaction(pb);
  334. }
  335.  
  336.  
  337. void DriverEntry(USBDeviceRef device, USBDeviceDescriptorPtr pDesc, UInt32 busPowerAvailable)
  338. {
  339. #pragma unused (busPowerAvailable)
  340.  
  341. static Boolean beenThereDoneThat = false;
  342.  
  343.     if(beenThereDoneThat)
  344.     {
  345.         USBExpertFatalError(device, kUSBInternalErr, "\pUSBHIDMacAllyTenKey is not reentrant", 12);
  346.         return;
  347.     }
  348.     beenThereDoneThat = true;
  349.     
  350. //    DebugStr("\pIn Keyboard Module Interface entry routine");
  351.     shimParamBlock.deviceDescriptor = *pDesc;                
  352.     shimParamBlock.transDepth = 0;                            
  353.     shimParamBlock.retryCount = kKeyboardRetryCount;
  354.     shimParamBlock.deviceRef = device;
  355.     shimParamBlock.interfaceRef = 0;
  356.     shimParamBlock.pipeRef = 0;
  357.     
  358.     shimParamBlock.deviceRef = device;        
  359.     shimParamBlock.interfaceRef = nil;        
  360.     shimParamBlock.pipeRef = nil;        
  361.     
  362.     InitParamBlock(device, &shimParamBlock.pb);
  363.     shimParamBlock.pb.pbLength = sizeof(usbMacAllyPBStruct);
  364.     shimParamBlock.pb.usbRefcon = 0;                
  365.  
  366.     myParamBlock.deviceDescriptor = *pDesc;                
  367.     myParamBlock.transDepth = 0;                            
  368.     myParamBlock.retryCount = kKeyboardRetryCount;
  369.     myParamBlock.deviceRef = device;
  370.     myParamBlock.interfaceRef = 0;
  371.     myParamBlock.pipeRef = 0;
  372.  
  373.     myParamBlock.deviceRef = device;        
  374.     myParamBlock.interfaceRef = nil;        
  375.     myParamBlock.pipeRef = nil;    
  376.     
  377.     myParamBlock.sendRawReportFlag = false;
  378.     myParamBlock.hidEmulationInit = false;
  379.     
  380.     InitParamBlock(device, &myParamBlock.pb);
  381.     myParamBlock.pb.pbLength = sizeof(usbMacAllyPBStruct);
  382.     myParamBlock.pb.usbRefcon = kFindInterface;        /* Start with setting the interface protocol */
  383.     
  384.     
  385.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  386.     InitiateTransaction(&myParamBlock.pb);
  387. }
  388.  
  389.  
  390.  
  391.